using FytSoa.Application.Erp.Param;
using FytSoa.Common.Enum;
using FytSoa.Domain.Erp;
using FytSoa.Sugar;
using FytSoa.Common.Utils;
using FytSoa.Common.Param;
using FytSoa.Common.Result;
using Mapster;
using Masuit.Tools.Reflection;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;

namespace FytSoa.Application.Erp;

/// <summary>
/// erp-产品入库服务接口
/// </summary>
[ApiExplorerSettings(GroupName = "v9")]
public class ErpInstockService : IApplicationService 
{
    private readonly SugarRepository<ErpInstock> _thisRepository;
    private readonly SugarRepository<ErpInstockProduct> _inStockProductRepository;
    private readonly SugarRepository<ErpPurchaseOrder> _orderRepository;
    private readonly SugarRepository<ErpPurchaseOrderInfo> _orderInfoRepository;
    private readonly ErpWarehouseProductService _warehouseProductService;
    private readonly SugarRepository<ErpProduceOrder> _productionRepository;
    private readonly ErpProductStockService _productStockService;
    private readonly ErpFlowUseService _flowUseService;
    private readonly ErpOperateLogService _operateLogService;
    public ErpInstockService(SugarRepository<ErpInstock> thisRepository
    ,SugarRepository<ErpInstockProduct> inStockProductRepository
    ,SugarRepository<ErpPurchaseOrder> orderRepository
    ,SugarRepository<ErpPurchaseOrderInfo> orderInfoRepository
    ,SugarRepository<ErpProduceOrder> productionRepository
    ,ErpWarehouseProductService warehouseProductService
    ,ErpProductStockService productStockService
    ,ErpFlowUseService flowUseService
    ,ErpOperateLogService operateLogService)
    {
        _thisRepository = thisRepository;
        _inStockProductRepository = inStockProductRepository;
        _orderRepository = orderRepository;
        _orderInfoRepository = orderInfoRepository;
        _productionRepository = productionRepository;
        _warehouseProductService = warehouseProductService;
        _productStockService = productStockService;
        _flowUseService = flowUseService;
        _operateLogService = operateLogService;
    }
    
    /// <summary>
    /// 查询所有——分页
    /// </summary>
    /// <param name="param"></param>
    /// <returns></returns>
    public async Task<PageResult<ErpInstockDto>> GetPagesAsync(PageParam param)
    {
        var query = await _thisRepository.AsQueryable()
            .WhereIF(!string.IsNullOrEmpty(param.Key),m=>m.Number.Contains(param.Key))
            .Includes(m=>m.Warehouse)
            .OrderByDescending(m=>m.Id)
            .ToPageAsync(param.Page, param.Limit);
        var result=query.Adapt<PageResult<ErpInstockDto>>();
        var orderIds = result.Items.Where(m => m.Type == ErpInStockTypeEnum.Purchase)
            .Select(m=>m.RelationId).ToList();
        if (orderIds.Count>0)
        {
            var orderList = await _orderRepository.GetListAsync(m => orderIds.Contains(m.Id));
            foreach (var item in result.Items.Where(m=>m.Type==ErpInStockTypeEnum.Purchase))
            {
                var orderModel = orderList.FirstOrDefault(m => m.Id == item.RelationId);
                if(orderModel==null) continue;
                item.Relation = new ErpInstockRelationDto()
                {
                    Id = orderModel.Id,
                    Number = orderModel.Number
                };
            }
        }
        //处理生产
        var productionIds = result.Items.Where(m => m.Type == ErpInStockTypeEnum.Production)
            .Select(m=>m.RelationId).ToList();
        if (productionIds.Count>0)
        {
            var orderList = await _productionRepository.GetListAsync(m => productionIds.Contains(m.Id));
            foreach (var item in result.Items.Where(m=>m.Type==ErpInStockTypeEnum.Production))
            {
                var orderModel = orderList.FirstOrDefault(m => m.Id == item.RelationId);
                if(orderModel==null) continue;
                item.Relation = new ErpInstockRelationDto()
                {
                    Id = orderModel.Id,
                    Number = orderModel.Number
                };
            }
        }
        return result;
    }

    /// <summary>
    /// 根据主键查询
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    [HttpGet("{id}")]
    public async Task<ErpInstockDto> GetAsync(long id)
    {
        var model = await _thisRepository.AsQueryable()
            .Includes(m=>m.Warehouse)
            .FirstAsync(m=>m.Id==id);
        var result=model.Adapt<ErpInstockDto>();
        if (model.Type==ErpInStockTypeEnum.Purchase)
        {
            var orderModel = await _orderRepository.GetFirstAsync(m => m.Id == model.RelationId);
            result.Relation = new ErpInstockRelationDto()
            {
                Id = orderModel.Id,
                Number = orderModel.Number
            };
        }
        if (model.Type==ErpInStockTypeEnum.Production)
        {
            var orderModel = await _productionRepository.GetFirstAsync(m => m.Id == model.RelationId);
            result.Relation = new ErpInstockRelationDto()
            {
                Id = orderModel.Id,
                Number = orderModel.Number
            };
        }
        result.ProductIds = await _inStockProductRepository.AsQueryable()
            .Where(m => m.InStockId == id)
            .Select(m => m.ProductId)
            .ToListAsync();

        result.Flow = await _flowUseService.GetFlowAsync(model.Id);
        return result;
    }

    /// <summary>
    /// 添加
    /// </summary>
    /// <param name="param"></param>
    /// <returns></returns>
    [UnitOfWork]
    public async Task AddAsync(ErpInStockAddParam param)
    {
        var toDay = await _thisRepository.CountAsync(m=>SqlFunc.DateIsSame(m.CreateTime,DateTime.Now));
        param.inStock.Number = "PI".ResNumber(toDay);
        var inStockId=await _thisRepository.InsertReturnSnowflakeIdAsync(param.inStock.Adapt<ErpInstock>());
        foreach (var item in param.Product)
        {
            item.InStockId = inStockId;
            item.WarehouseId = param.inStock.WarehouseId;
        }
        await _inStockProductRepository.InsertRangeAsync(param.Product.Adapt<List<ErpInstockProduct>>());

        // 处理采购一下逻辑
        if (param.inStock.Type==ErpInStockTypeEnum.Purchase)
        {
            // 更改采购入库的商品状态信息
            var productIds = param.Product.Select(m => m.ProductId);
            await _orderInfoRepository.UpdateAsync(m => new ErpPurchaseOrderInfo()
            {
                IsInStock = true
            },m=>m.OrderId==param.inStock.RelationId && productIds.Contains(m.ProductId));
        }
        
        await _operateLogService.AddAsync(new ErpOperateLogDto()
        {
            OperateId = inStockId,
            Type = (int)ErpOperateEnum.InStock,
            Remark = "创建了产品入库信息【"+param.inStock.Number+"】"
        });
        
        if (param.inStock.FlowId!=0)
        {
            await _flowUseService.AddAsync(new ErpFlowUseDto()
            {
                FlowId=param.inStock.FlowId,
                UseId=inStockId,
                Type = FlowTypeEnum.InStock,
            });
        }
    }

    /// <summary>
    /// 修改
    /// </summary>
    /// <param name="param"></param>
    /// <returns></returns>
    [UnitOfWork]
    public async Task ModifyAsync(ErpInStockAddParam param)
    {
        await _thisRepository.UpdateAsync(param.inStock.Adapt<ErpInstock>());
        await _inStockProductRepository.DeleteAsync(m => m.InStockId == param.inStock.Id);
        foreach (var item in param.Product)
        {
            item.InStockId = param.inStock.Id;
            item.WarehouseId = param.inStock.WarehouseId;
        }
        await _inStockProductRepository.InsertRangeAsync(param.Product.Adapt<List<ErpInstockProduct>>());
        
        // 处理采购一下逻辑
        if (param.inStock.Type==ErpInStockTypeEnum.Purchase)
        {
            // 更改采购入库的商品状态信息
            var productIds = param.Product.Select(m => m.ProductId);
            await _orderInfoRepository.UpdateAsync(m => new ErpPurchaseOrderInfo()
            {
                IsInStock = true
            },m=>m.OrderId==param.inStock.RelationId && productIds.Contains(m.ProductId));
            // 不是的，更改为非入库
            await _orderInfoRepository.UpdateAsync(m => new ErpPurchaseOrderInfo()
            {
                IsInStock = false
            },m=>m.OrderId==param.inStock.RelationId && !productIds.Contains(m.ProductId));
        }
        
        if (param.inStock.Status == ErpAuditEnum.NotReviewed)
        {
            await _flowUseService.ModifyAsync(new ErpFlowUseDto()
            {
                FlowId = param.inStock.FlowId,
                UseId = param.inStock.Id,
                Type = FlowTypeEnum.InStock,
            });
        }
        
        await _operateLogService.AddAsync(new ErpOperateLogDto()
        {
            OperateId = param.inStock.Id,
            Type = (int)ErpOperateEnum.InStock,
            Remark = "编辑了产品入库信息~"
        });
    }

    /// <summary>
    /// 审核状态
    /// </summary>
    /// <param name="param"></param>
    /// <returns></returns>
    [UnitOfWork]
    public async Task ModifyStatusAsync(ErpStatusParam param)
    {
        var model = await _thisRepository.GetByIdAsync(param.Ids[0]);
        await _thisRepository.UpdateAsync(m=>new ErpInstock()
        {
            Status = param.Status
        },m=>m.Id==param.Ids[0]);

        if (param.Status==ErpAuditEnum.Reviewed)
        {
            #region 产品入库操作
            var instockList = await _inStockProductRepository.GetListAsync(m => m.InStockId == param.Ids[0]);
            var productStockList = new List<ErpProductStock>();
            foreach (var item in instockList)
            {
                productStockList.Add(new ErpProductStock()
                {
                    ProductId = item.ProductId,
                    Count = item.Count
                });
            }

            await _productStockService.AddAsync(productStockList);
            #endregion
        
            #region 入库产品详细

            var warehouseProductList = new List<ErpWarehouseProduct>();
            foreach (var item in instockList)
            {
                warehouseProductList.Add(new ErpWarehouseProduct()
                {
                    WarehouseId = model.WarehouseId,
                    ProductId = item.ProductId,
                    Count = item.Count
                });
            }
            await _warehouseProductService.AddAsync(warehouseProductList);
            #endregion
        }
        
        if (param.Status==ErpAuditEnum.InReview)
        {
            foreach (var item in param.Ids)
            {
                await _flowUseService.StartAuditAsync(item, FlowTypeEnum.InStock);
            }
        }
        
        await _operateLogService.AddAsync(new ErpOperateLogDto()
        {
            OperateId = param.Ids[0],
            Type = (int)ErpOperateEnum.PurchaseOrder,
            Remark = "对产品入库做了审核"+param.Status.GetDescription()+"操作"
        });
    }

    /// <summary>
    /// 删除,支持批量
    /// </summary>
    /// <param name="ids"></param>
    /// <returns></returns>
    [HttpDelete,UnitOfWork]
    public async Task DeleteAsync([FromBody] List<long> ids)
    {
        await _thisRepository.DeleteAsync(m=>ids.Contains(m.Id));
        await _inStockProductRepository.DeleteAsync(m => ids.Contains(m.InStockId));
        await _flowUseService.DeleteAsync(ids);
    }
}
